#include <iostream>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <unistd.h>

using std::cout;
using std::endl;

#define ERR_CHECK(var, val, msg)                \
    if (var == val)                             \
    {                                           \
        cout << msg << strerror(errno) << endl; \
    }

void test()
{
    int sockFd = socket(AF_INET, SOCK_STREAM, 0);
    ERR_CHECK(sockFd, -1, "socket");

    sockaddr_in addr{};
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    addr.sin_port = htons(12345);
    addr.sin_family = AF_INET;

    int ret = connect(sockFd, (sockaddr *)&addr, sizeof(addr));
    ERR_CHECK(ret, -1, "connect");

    int stdFd = fileno(stdin);
    fd_set rdset;

    char buf[1024];
    int i = 3;
    while (i > 0)
    {
        FD_ZERO(&rdset);
        FD_SET(sockFd, &rdset);
        FD_SET(stdFd, &rdset);

        int ret = select(sockFd + 1, &rdset, 0, 0, 0);
        ERR_CHECK(ret, -1, "select");
        if (FD_ISSET(stdFd, &rdset))
        {
            memset(buf, 0, strlen(buf));
            ret = read(stdFd, buf, sizeof(buf));
            write(sockFd, buf, strlen(buf));
        }
        if (FD_ISSET(sockFd, &rdset))
        {
            memset(buf, 0, strlen(buf));
            read(sockFd, buf, sizeof(buf));
            cout << buf;
        }
        i--;
    }
    close(sockFd);
}

int main(int args, char *argv[])
{
    test();
    return 0;
}